# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: api\handlers\worker_frontend\status.py
__author__ = "Attila Gerendi (Sanyi)"
import logging, uuid
from api.handlers.worker_frontend import WorkerFrontendResourceHandler
from api.classes.worker.auto import *
from server.http_responses.http_errors import Http409 as ApiError409
from server.http_responses.http_status_codes import Http204
from helpers.http_clients.status_api import ScanStatusClient
from helpers.http_clients.exceptions import *
from settings_provider import settings
from helpers.hashing import md5
from db.tables.workers import WorkerAuthorization
from helpers.constants.jobs import ScanAppTypes

logger = logging.getLogger("backend.api.handlers.worker.status")


class WorkerStatus(WorkerFrontendResourceHandler):
    def register(self, body, **_):
        api_key = str(uuid.uuid4()).replace("-", "")
        master_endpoint = self.settings_storage.get("master_endpoint")
        if master_endpoint:
            try:
                authorization = self.settings_storage.get(
                    "authorization", WorkerAuthorization.DETACHED
                )
                if authorization == WorkerAuthorization.AUTHORIZED:
                    self.un_register()
            except Exception as e:
                logging.warning("un_register failed with %s", e)

            registration_data = ClsWorkerRegistrationData(**body)
            cli = ScanStatusClient(
                registration_data.master_endpoint,
                ssl_verify=registration_data.ssl_verify_master,
            )
            logging.debug("connecting to %s", registration_data.master_endpoint)
            worker_endpoint = registration_data.get("worker_endpoint")
            if not worker_endpoint:
                worker_endpoint = settings.get("worker_endpoint")
            try:
                worker_info = cli.post_request(
                    "/workers/",
                    data=dict(
                        scanning_app=ScanAppTypes.WVS,
                        endpoint=worker_endpoint,
                        description=registration_data.description,
                        ssl_verify=registration_data.ssl_verify_worker,
                        api_key="0" + api_key,
                        app_version=settings.get("version_info", {}).get(
                            "str", "11.0.0"
                        ),
                        license_hash=md5(self.license.license_key),
                    ),
                )
            except HTTP404:
                raise ApiError409(
                    "The Main Installation could not be accessed at the specified URL [404]"
                )
            except HTTP400:
                raise ApiError409(
                    "The Main Installation could not be accessed at the specified URL [400]"
                )
            except HTTP500:
                raise ApiError409("The Main Installation responded with error [500]")
            except HTTP409 as e:
                message = "HTTP 409"
                try:
                    message = e.result["message"]
                except Exception:
                    pass

                raise ApiError409(
                    "The Main Installation responded with error [%s]" % message
                )
            except HTTPException as e:
                logger.exception("status api request failed %s", e.result)
                raise ApiError409("The Main Installation responded with an error.")
            except RequestError as e:
                logger.exception("status api request failed with %s", e)
                raise ApiError409("Could not connect to the Main Installation")

            self.settings_storage.set(
                "master_endpoint", registration_data.master_endpoint
            )
            self.settings_storage.set(
                "ssl_verify_master", registration_data.ssl_verify_master
            )
            self.settings_storage.set("api_key", api_key)
            self.settings_storage.set("worker_id", worker_info["worker_id"])
            self.settings_storage.set("authorization", worker_info["authorization"])
            return Http204()

    def un_register(self, **_):
        master_endpoint = self.settings_storage.get("master_endpoint")
        if master_endpoint is None:
            raise HTTP409("Scanning Engine is not registered")
        master_endpoint = self.settings_storage.get("master_endpoint")
        ssl_verify_master = self.settings_storage.get("ssl_verify_master")
        api_key = self.settings_storage.get("api_key")
        self.settings_storage.delete("master_endpoint")
        cli = ScanStatusClient(master_endpoint, ssl_verify=ssl_verify_master)
        try:
            cli.delete_request("/workers/%s" % (api_key,))
        except Exception as e:
            logger.exception("status api request failed with %s", e)

        return Http204()

    def check_communication(self, **_):
        master_endpoint = self.settings_storage.get("master_endpoint")
        if master_endpoint is None:
            raise HTTP409("Scanning Engine is not registered")
        cli = ScanStatusClient(
            self.settings_storage.get("master_endpoint"),
            ssl_verify=self.settings_storage.get("ssl_verify_master"),
        )
        try:
            cli.get_request("/workers/" + self.settings_storage.get("worker_id"))
        except HTTP404:
            raise ApiError409(
                "The Main Installation could not be accessed at the specified URL [404]"
            )
        except HTTP400:
            raise ApiError409(
                "The Main Installation could not be accessed at the specified URL [400]"
            )
        except HTTP500:
            raise ApiError409("The Main Installation responded with error [500]")
        except HTTP409 as e:
            message = "HTTP 409"
            try:
                message = e.result["message"]
            except Exception:
                pass

            raise ApiError409(
                "The Main Installation responded with error [%s]" % message
            )
        except HTTPException as e:
            logger.exception("status api request failed %s", e.result)
            raise ApiError409("The Main Installation responded with an error.")
        except RequestError as e:
            logger.exception("status api request failed with %s", e)
            raise ApiError409("Could not connect to the Main Installation")

        return Http204()

    def get_status(self, **_):
        master_endpoint = self.settings_storage.get("master_endpoint")
        if master_endpoint is None:
            return ClsWorkerStatusData(authorization=WorkerAuthorization.NONE)
        authorization = self.settings_storage.get(
            "authorization", WorkerAuthorization.DETACHED
        )
        status = self.settings_storage.get("status", None)
        if authorization in (
            WorkerAuthorization.PENDING,
            WorkerAuthorization.AUTHORIZED,
            WorkerAuthorization.REJECTED,
        ):
            cli = ScanStatusClient(
                self.settings_storage.get("master_endpoint"),
                ssl_verify=self.settings_storage.get("ssl_verify_master"),
            )
            try:
                r = cli.get_request(
                    "/workers/" + self.settings_storage.get("worker_id")
                )
                authorization = r["authorization"]
            except HTTP404:
                logger.exception("get_status: invalid master response (404)")
            except HTTP400:
                logger.exception(
                    "get_status: master does not understand the worker. Probably version mismatch."
                )
            except HTTP500:
                logger.exception("get_status: invalid master response (500)")
            except HTTP409 as e:
                message = "HTTP 409"
                try:
                    message = e.result["message"]
                except Exception:
                    pass

                if "Scanning Engine not found" in message:
                    authorization = WorkerAuthorization.DETACHED
                else:
                    if "Scanning Engine authentication error" in message:
                        authorization = WorkerAuthorization.DETACHED
                logger.exception("get_status: master reported that: %s" % message)
            except HTTPException as e:
                logger.exception("get_status: status api request failed %s", e.result)
            except RequestError as e:
                logger.exception("get_status: status api request failed with %s", e)

            result = dict(
                authorization=authorization,
                master_endpoint=master_endpoint,
                ssl_verify_master=self.settings_storage.get("ssl_verify_master", False),
                status=status,
            )
            return ClsWorkerStatusData(**result)

    def set_offline(self, **_):
        master_endpoint = self.settings_storage.get("master_endpoint")
        if master_endpoint is None:
            raise HTTP409("Scanning Engine is not registered")
        if self.settings_storage.get("status") not in ("online", "suspended"):
            raise HTTP409(
                "invalid Scanning Engine status [%s]",
                self.settings_storage.get("status"),
            )
        self.settings_storage.set("status", "offline")
        cli = ScanStatusClient(
            self.settings_storage.get("master_endpoint"),
            ssl_verify=self.settings_storage.get("ssl_verify_master"),
        )
        try:
            cli.post_request(
                "/workers/%s/set_status" % (self.settings_storage.get("api_key"),),
                data=dict(
                    status="offline", license=get_local_license().get("license_key")
                ),
            )
        except HTTPException as e:
            logger.exception("status api request failed %s", e.result)
            raise ApiError409("Main Installation response error", details=e.result)
        except RequestError as e:
            logger.exception("status api request failed with %s", e)
            raise ApiError409("Could not connect to the Main Installation")

        return Http204()

    def set_online(self, **_):
        master_endpoint = self.settings_storage.get("master_endpoint")
        if master_endpoint is None:
            raise HTTP409("Scanning Engine is not registered")
        if self.settings_storage.get("status") not in ("offline", "suspended"):
            raise HTTP409(
                "invalid Scanning Engine status [%s]",
                self.settings_storage.get("status"),
            )
        self.settings_storage.set("status", "online")
        cli = ScanStatusClient(
            self.settings_storage.get("master_endpoint"),
            ssl_verify=self.settings_storage.get("ssl_verify_master"),
        )
        try:
            cli.post_request(
                "/workers/%s/set_status" % (self.settings_storage.get("api_key"),),
                data=dict(
                    status="online", license=get_local_license().get("license_key")
                ),
            )
        except HTTPException as e:
            logger.exception("status api request failed %s", e.result)
            raise ApiError409("Main Installation response error", details=e.result)
        except RequestError as e:
            logger.exception("status api request failed with %s", e)
            raise ApiError409("Could not connect to the Main Installation")

    def resume_accepting_new_jobs(self, **_):
        master_endpoint = self.settings_storage.get("master_endpoint")
        if master_endpoint is None:
            raise HTTP409("Scanning Engine is not registered")
        if self.settings_storage.get("status") != "suspended":
            raise HTTP409(
                "invalid Scanning Engine status [%s]",
                self.settings_storage.get("status"),
            )
        cli = ScanStatusClient(
            self.settings_storage.get("master_endpoint"),
            ssl_verify=self.settings_storage.get("ssl_verify_master"),
        )
        self.settings_storage.set("status", "online")
        try:
            cli.post_request(
                "/workers/%s/set_status" % (self.settings_storage.get("api_key"),),
                data=dict(
                    status="online", license=get_local_license().get("license_key")
                ),
            )
        except HTTPException as e:
            logger.exception("status api request failed %s", e.result)
            raise ApiError409("Main Installation response error", details=e.result)
        except RequestError as e:
            logger.exception("status api request failed with %s", e)
            raise ApiError409("Could not connect to the Main Installation")

        return Http204()

    def suspend_accepting_new_jobs(self, **_):
        master_endpoint = self.settings_storage.get("master_endpoint")
        if master_endpoint is None:
            raise HTTP409("Scanning Engine is not registered")
        if self.settings_storage.get("status") != "online":
            raise HTTP409(
                "invalid Scanning Engine status [%s]",
                self.settings_storage.get("status"),
            )
        self.settings_storage.set("status", "suspended")
        cli = ScanStatusClient(
            self.settings_storage.get("master_endpoint"),
            ssl_verify=self.settings_storage.get("ssl_verify_master"),
        )
        try:
            cli.post_request(
                "/workers/%s/set_status" % (self.settings_storage.get("api_key"),),
                data=dict(
                    status="suspended", license=get_local_license().get("license_key")
                ),
            )
        except HTTPException as e:
            logger.exception("status api request failed %s", e.result)
            raise ApiError409("Main Installation response error", details=e.result)
        except RequestError as e:
            logger.exception("status api request failed with %s", e)
            raise ApiError409("Could not connect to the Main Installation")

        return Http204()
